package com.huawei.hwclouds.lubanops.demo.common.client.impl;

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import com.huawei.hwclouds.lubanops.demo.common.exception.common.InternalErrorException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;

import com.huawei.hwclouds.lubanops.demo.common.client.HeaderFactory;

/**
 * 发送http请求的基类
 *
 * @author yefeng
 */
public class ApacheHttpClientCommon extends ApacheHttpClientBase {

    public final static int DEFAULT_MAX_TOTAL = 200;

    /**
     * 系统默认的实例
     */
    private final static ApacheHttpClientCommon STATIC_INNER_CLASS_SINGLETON = new ApacheHttpClientCommon(
        DEFAULT_MAX_TOTAL, 30, 5000);

    protected PoolingHttpClientConnectionManager connectionManager;

    private CloseableHttpClient httpClient;

    /**
     * 指定maxTotal和idle时间
     *
     * @param maxTotal
     * @param maxIdleTimeInSeconds
     * @return
     */
    public ApacheHttpClientCommon(int maxTotal, int maxIdleTimeInSeconds, int defaultTimeout) {
        super(defaultTimeout);
        init(maxTotal, maxIdleTimeInSeconds, defaultTimeout);
    }

    /**
     * 指定maxTotal和idle时间,默认超时时间，以及header factory
     *
     * @param maxTotal
     * @param maxIdleTimeInSeconds
     * @return
     */
    public ApacheHttpClientCommon(int maxTotal, int maxIdleTimeInSeconds, int defaultTimeout,
        HeaderFactory headerFactory) {
        super(defaultTimeout, headerFactory);
        init(maxTotal, maxIdleTimeInSeconds, defaultTimeout);
    }

    /**
     * 获取单例，所有的公共的http发送请求的实例 <br>
     *
     * @return
     * @author y00438022
     * @since 2020年2月29日
     */
    public static ApacheHttpClientCommon getDefaultInstance() {
        return STATIC_INNER_CLASS_SINGLETON;
    }

    /**
     * @param maxTotal          最大的链接数，包括连接池的总数，以及每个路由设置的连接数，现在设置成一样的
     * @param idleTimeInSeconds 如果连接多少时间没有数据会掐断。主要解决有一些连接被中间网络设备掐断的场景。
     */
    protected void init(int maxTotal, int idleTimeInSeconds, int defaultTimeout) {



        SSLContext sslContext = null;
        try {
            sslContext = SSLContexts.custom().loadTrustMaterial(new TheTrustStrategy()).setProtocol("TLSv1.2").build();
        } catch (KeyManagementException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        } catch (NoSuchAlgorithmException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        } catch (KeyStoreException e) {
            throw new InternalErrorException("failed to get SSLContext", e);
        }
        connectionManager = (PoolingHttpClientConnectionManager) ApacheHttpClientHelp.getConnectionManager(sslContext);
        connectionManager.setMaxTotal(maxTotal);
        httpClient = (CloseableHttpClient) ApacheHttpClientHelp.getHttpclient(connectionManager, idleTimeInSeconds);
    }

    @Override
    protected CloseableHttpClient getHttpClient() {
        return httpClient;
    }

    public static class TheTrustStrategy implements TrustStrategy {
        @Override
        public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
            return true;
        }
    }

}
